const fs = require("fs");
const path = require("path");
const moment = require("moment");
const { createCanvas } = require("canvas");
/**
 * resolve path
 * @param _path
 */
const resolve = (_path) => path.resolve(__dirname, "..", _path);

/**
 * 检查数据源文件是否存在
 * @param path
 * @param mkdir
 * @returns {boolean}
 */
const checkFileExists = (path, mkdir) => {
  try {
    fs.statSync(path);
    return fs.existsSync(path);
  } catch (e) {
    if (mkdir) {
      fs.mkdirSync(path, { recursive: true });
    }
    return false;
  }
};

/**
 * 判断文件夹是否存在
 * @param path
 * @param mkdir
 * @returns {boolean}
 */
const checkFolderExist = (path, mkdir) => {
  if (!fs.existsSync(path)) {
    if (mkdir) {
      fs.mkdirSync(path, { recursive: true });
    }
    return false;
  } else {
    return true;
  }
};

/**
 * 检查时间是否合法
 * @param _time
 * @returns {boolean}
 */
const checkTime = (_time) => {
  try {
    moment(_time);
    if (moment.utc().diff(_time, "days") > 10) {
      // 最多获取两周数据
      return false;
    } else {
      return true;
    }
  } catch (error) {
    return false;
  }
};

/**
 * 获取文件树
 * @param _path
 * @returns {Array}
 */
const getFileList = (_path) => {
  const result = [];
  function finder(path_) {
    let files = fs.readdirSync(path_);
    files.forEach((val, index) => {
      let fPath = path.join(path_, val);
      let stats = fs.statSync(fPath);
      if (stats.isDirectory()) finder(fPath);
      if (stats.isFile()) result.push(val);
    });
  }
  finder(_path);
  return result;
};

/**
 * 获取文件扩展名
 * @param _string
 * @returns {*}
 */
const getFileExt = (_string) => {
  if (_string && _string.split) {
    const _arr = _string.split(".");
    return _arr[_arr.length - 1];
  } else {
    return false;
  }
};

const zeroize = function (val, filLength = 3) {
  return Number(val).toFixed().padStart(filLength, "0");
};

/**
 *
 * @param {*} target
 * @param {Array} ExtraParams
 * @returns
 */
const rejectExtraParams = function (target, ExtraParams) {
  return Object.fromEntries(
    Object.entries(target).filter(([key]) => !ExtraParams.includes(key))
  );
};

const uuid = function () {
  var s = [];

  var hexDigits = "0123456789abcdef";

  for (var i = 0; i < 36; i++) {
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
  }

  s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010

  s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01

  s[8] = s[13] = s[18] = s[23] = "-";

  var uuid = s.join("");

  return uuid;
};

const simpleUUid = function (prefix) {
  const now = new Date().getTime();
  return prefix + "_" + now.toString(16);
};

const isFileExisted = function (path_way) {
  return new Promise((resolve, reject) => {
    fs.access(path_way, (err) => {
      if (err) {
        reject(false); //"不存在"
      } else {
        resolve(true); //"存在"
      }
    });
  });
};

const getFourSurroundingIndex = function (x, y) {
  const minX = Math.floor(x);
  const maxX = Math.ceil(x);
  const minY = Math.floor(y);
  const maxY = Math.ceil(y);
  return [minX, maxX, minY, maxY];
};

const exchangeIndex = (x, y, w) => y * w + x;

const BilinearInterpolation = function (
  source,
  sourceW,
  sourceH,
  targetW,
  targetH
) {
  // const TargetData = [];
  const TargetData = Buffer.allocUnsafe(targetW * targetH * 4);

  for (let y = 0; y < targetH; y++) {
    for (let x = 0; x < targetW; x++) {
      const srcX = x * (sourceW / targetW);
      const srcY = y * (sourceH / targetH);
      let [minX, maxX, minY, maxY] = getFourSurroundingIndex(srcX, srcY);

      if (maxX > sourceW - 1 || maxY > sourceH - 1) {
        (maxX = sourceW - 1), (maxY = sourceH - 1);
      }

      const leftTop = source[exchangeIndex(minX, minY, sourceW)]; //左上 整数点值
      const rightTop = source[exchangeIndex(maxX, minY, sourceW)]; //右上 整数点值
      const leftBottom = source[exchangeIndex(minX, maxY, sourceW)]; //左下 整数点值
      const rightBottom = source[exchangeIndex(maxX, maxY, sourceW)]; //右下 整数点值

      const M =
        maxX - minX == 0
          ? leftTop
          : ((srcX - minX) / (maxX - minX)) * (rightTop - leftTop) + leftTop;
      const N =
        maxX - minX == 0
          ? leftBottom
          : ((srcX - minX) / (maxX - minX)) * (rightBottom - leftBottom) +
            leftBottom;
      const P =
        maxY - minY == 0 ? M : ((srcY - minY) / (maxY - minY)) * (N - M) + M;

      // TargetData[y*targetW+x] = P
      TargetData.writeFloatLE(P, (y * targetW + x) * 4);
    }
  }
  return TargetData;
};

const CreateCanvas = function (imageData, w, h) {
  const canvas = createCanvas(w, h);
  const ctx = canvas.getContext("2d");
  ctx.putImageData(imageData, 0, 0, 0, 0, w, h);
  const base64 = canvas.toDataURL("image/png", 1);
  const imgBuffer = Buffer.from(
    base64.replace("data:image/png;base64,", ""),
    "base64"
  );
  return imgBuffer;
};

const maxOrMin = (data) => {
  let min = 999999;
  let max = -999999;
  for (let i = 0; i < data.length; i++) {
    if (Number.parseInt(data[i]) != 9999) {
      if (data[i] < min) min = data[i];
      else if (data[i] > max) max = data[i];
    }
  }
  return [min, max];
};

module.exports = {
  checkTime,
  resolve,
  checkFileExists,
  checkFolderExist,
  getFileList,
  getFileExt,
  zeroize,
  rejectExtraParams,
  uuid,
  simpleUUid,
  isFileExisted,
  BilinearInterpolation,
  maxOrMin,
  CreateCanvas,
};
